﻿using System;
using System.Collections.Generic;

using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Qizx.Api;

namespace System.Qizx.Xdm {
    internal class XdmNameTable {
        // Fields
        private Dictionary<XdmName, XdmName> _entries;
        private XmlNameTable nameTable;
        private XdmDocument ownerDocument;
        private XdmName _dummy;
        private Dictionary<XdmName, XdmName>[] _exEntries;

        // Methods
        public XdmNameTable(XdmDocument document) {
            this.ownerDocument = document;
            this.nameTable = document.NameTable;
            this._entries = new Dictionary<XdmName, XdmName>(0x20);
            _dummy = new XdmName(string.Empty, string.Empty, string.Empty, document, null);
        }

        public XdmName AddName(string prefix, string localName, string ns, IXdmSchemaInfo schemaInfo) {
            if (prefix == null) {
                prefix = string.Empty;
            }
            if (ns == null) {
                ns = string.Empty;
            }
            Dictionary<XdmName, XdmName> entries = _entries;
            if (ownerDocument.ActiveSchemaSetIndex > 0) {
                int index = ownerDocument.ActiveSchemaSetIndex - 1;
                if (_exEntries == null) {
                    _exEntries = new Dictionary<XdmName, XdmName>[index + 1];
                } else if (index >= _exEntries.Length) {
                    Dictionary<XdmName, XdmName>[] ents = new Dictionary<XdmName, XdmName>[index + 1];
                    ents[index] = new Dictionary<XdmName, XdmName>();
                    Array.Copy(_exEntries, ents, _exEntries.Length);
                    _exEntries = ents;
                }
                entries = _exEntries[index];
                if (entries == null) {
                    _exEntries[index] = new Dictionary<XdmName, XdmName>();
                    entries = _exEntries[index];
                }
            }

            _dummy.Update(prefix, localName, ns);
            XdmName cacheValue = null;
            XdmName name2 = null;
            if (entries.TryGetValue(_dummy, out cacheValue)) {
                XdmName name = cacheValue;
                while (name != null) {
                    if (name.Equals(schemaInfo)) {
                        return name;
                    }
                    name = name._next;
                }
                name2 = XdmName.Create(prefix, localName, ns, this.ownerDocument, cacheValue);
                name2.Update(schemaInfo);
                entries[name2] = name2;
            } else {
                name2 = XdmName.Create(prefix, localName, ns, this.ownerDocument, null);
                name2.Update(schemaInfo);
                entries[name2] = name2;
            }
            return name2;
        }

        public XdmName GetName(string prefix, string localName, string ns, IXmlSchemaInfo schemaInfo) {
            if (prefix == null) {
                prefix = string.Empty;
            }
            if (ns == null) {
                ns = string.Empty;
            }
            _dummy.Update(prefix, localName, ns);
            XdmName cacheValue = null;
            if (_entries.TryGetValue(_dummy, out cacheValue)) {
                XdmName name = cacheValue;
                while (name != null) {
                    if (name.Equals(schemaInfo)) {
                        return name;
                    }
                    name = name._next;
                }
            }
            if (_exEntries != null) {
                foreach (Dictionary<XdmName, XdmName> entries in _exEntries) {
                    if (entries.TryGetValue(_dummy, out cacheValue)) {
                        XdmName name = cacheValue;
                        while (name != null) {
                            if (name.Equals(schemaInfo)) {
                                return name;
                            }
                            name = name._next;
                        }
                    }
                }
            }
            return null;
        }

    }


}
